home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
xlisp_21.zoo
/
xlread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-02-28
|
18KB
|
866 lines
/* xlread - xlisp expression input routine */
/* Copyright (c) 1985, by David Michael Betz
All Rights Reserved
Permission is granted for unrestricted non-commercial use */
#include "xlisp.h"
/* symbol parser modes */
#define DONE 0
#define NORMAL 1
#define ESCAPE 2
/* external variables */
extern LVAL s_stdout,true,s_dot;
extern LVAL s_quote,s_function,s_bquote,s_comma,s_comat;
extern LVAL s_rtable,k_wspace,k_const,k_nmacro,k_tmacro;
extern LVAL k_sescape,k_mescape;
extern char buf[];
/* external routines */
extern FILE *osaopen();
extern double atof();
extern ITYPE;
#define WSPACE "\t \f\r\n"
#define CONST1 "!$%&*+-./0123456789:<=>?@[]^_{}~"
#define CONST2 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
/* forward declarations */
FORWARD LVAL callmacro();
FORWARD LVAL psymbol(),punintern();
FORWARD LVAL pnumber(),pquote(),plist(),pvector(),pstruct();
FORWARD LVAL readlist(),tentry();
/* xlload - load a file of xlisp expressions */
int xlload(fname,vflag,pflag)
char *fname; int vflag,pflag;
{
char fullname[STRMAX+1];
LVAL fptr,expr;
CONTEXT cntxt;
FILE *fp;
int sts;
/* protect some pointers */
xlstkcheck(2);
xlsave(fptr);
xlsave(expr);
/* default the extension */
if (needsextension(fname)) {
strcpy(fullname,fname);
strcat(fullname,".lsp");
fname = fullname;
}
/* allocate a file node */
fptr = cvfile(NULL);
/* open the file */
if ((fp = osaopen(fname,"r")) == NULL) {
xlpopn(2);
return (FALSE);
}
setfile(fptr,fp);
/* print the information line */
if (vflag)
{ sprintf(buf,"; loading \"%s\"\n",fname); stdputstr(buf); }
/* read, evaluate and possibly print each expression in the file */
xlbegin(&cntxt,CF_ERROR,true);
if (setjmp(cntxt.c_jmpbuf))
sts = FALSE;
else {
while (xlread(fptr,&expr,FALSE)) {
expr = xleval(expr);
if (pflag)
stdprint(expr);
}
sts = TRUE;
}
xlend(&cntxt);
/* close the file */
osclose(getfile(fptr));
setfile(fptr,NULL);
/* restore the stack */
xlpopn(2);
/* return status */
return (sts);
}
/* xlread - read an xlisp expression */
int xlread(fptr,pval,rflag)
LVAL fptr,*pval; int rflag;
{
int sts;
/* read an expression */
while ((sts = readone(fptr,pval)) == FALSE)
;
/* return status */
return (sts == EOF ? FALSE : TRUE);
}
/* readone - attempt to read a single expression */
int readone(fptr,pval)
LVAL fptr,*pval;
{
LVAL val,type;
int ch;
/* get a character and check for EOF */
if ((ch = xlgetc(fptr)) == EOF)
return (EOF);
/* handle white space */
if ((type = tentry(ch)) == k_wspace)
return (FALSE);
/* handle symbol constituents */
else if (type == k_const) {
xlungetc(fptr,ch);
*pval = psymbol(fptr);
return (TRUE);
}
/* handle single and multiple escapes */
else if (type == k_sescape || type == k_mescape) {
xlungetc(fptr,ch);
*pval = psymbol(fptr);
return (TRUE);
}
/* handle read macros */
else if (consp(type)) {
if ((val = callmacro(fptr,ch)) && consp(val)) {
*pval = car(val);
return (TRUE);
}
else
return (FALSE);
}
/* handle illegal characters */
else
xlerror("illegal character",cvfixnum((FIXTYPE)ch));
}
/* rmhash - read macro for '#' */
LVAL rmhash()
{
LVAL fptr,mch,val;
int escflag,ch;
/* protect some pointers */
xlsave1(val);
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* make the return value */
val = consa(NIL);
/* check the next character */
switch (ch = xlgetc(fptr)) {
case '\'':
rplaca(val,pquote(fptr,s_function));
break;
case '(':
xlungetc(fptr,ch);
rplaca(val,pvector(fptr));
break;
case 'b':
case 'B':
rplaca(val,pnumber(fptr,2));
break;
case 'o':
case 'O':
rplaca(val,pnumber(fptr,8));
break;
case 'x':
case 'X':
rplaca(val,pnumber(fptr,16));
break;
case 's':
case 'S':
rplaca(val,pstruct(fptr));
break;
case '\\':
xlungetc(fptr,ch);
pname(fptr,&escflag);
ch = buf[0];
if (strlen(buf) > 1) {
upcase(buf);
if (strcmp(buf,"NEWLINE") == 0)
ch = '\n';
else if (strcmp(buf,"SPACE") == 0)
ch = ' ';
else
xlerror("unknown character name",cvstring(buf));
}
rplaca(val,cvchar(ch));
break;
case ':':
rplaca(val,punintern(fptr));
break;
case '|':
pcomment(fptr);
val = NIL;
break;
default:
xlerror("illegal character after #",cvfixnum((FIXTYPE)ch));
}
/* restore the stack */
xlpop();
/* return the value */
return (val);
}
/* rmquote - read macro for '\'' */
LVAL rmquote()
{
LVAL fptr,mch;
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* parse the quoted expression */
return (consa(pquote(fptr,s_quote)));
}
/* rmdquote - read macro for '"' */
LVAL rmdquote()
{
unsigned char buf[STRMAX+1],*p,*sptr;
LVAL fptr,str,newstr,mch;
int len,blen,ch,d2,d3;
/* protect some pointers */
xlsave1(str);
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* loop looking for a closing quote */
len = blen = 0; p = buf;
while ((ch = checkeof(fptr)) != '"') {
/* handle escaped characters */
switch (ch) {
case '\\':
switch (ch = checkeof(fptr)) {
case 't':
ch = '\011';
break;
case 'n':
ch = '\012';
break;
case 'f':
ch = '\014';
break;
case 'r':
ch = '\015';
break;
default:
if (ch >= '0' && ch <= '7') {
d2 = checkeof(fptr);
d3 = checkeof(fptr);
if (d2 < '0' || d2 > '7'
|| d3 < '0' || d3 > '7')
xlfail("invalid octal digit");
ch -= '0'; d2 -= '0'; d3 -= '0';
ch = (ch << 6) | (d2 << 3) | d3;
}
break;
}
}
/* check for buffer overflow */
if (blen >= STRMAX) {
newstr = newstring(len + STRMAX + 1);
sptr = getstring(newstr); *sptr = '\0';
if (str) strcat(sptr,getstring(str));
*p = '\0'; strcat(sptr,buf);
p = buf; blen = 0;
len += STRMAX;
str = newstr;
}
/* store the character */
*p++ = ch; ++blen;
}
/* append the last substring */
if (str == NIL || blen) {
newstr = newstring(len + blen + 1);
sptr = getstring(newstr); *sptr = '\0';
if (str) strcat(sptr,getstring(str));
*p = '\0'; strcat(sptr,buf);
str = newstr;
}
/* restore the stack */
xlpop();
/* return the new string */
return (consa(str));
}
/* rmbquote - read macro for '`' */
LVAL rmbquote()
{
LVAL fptr,mch;
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* parse the quoted expression */
return (consa(pquote(fptr,s_bquote)));
}
/* rmcomma - read macro for ',' */
LVAL rmcomma()
{
LVAL fptr,mch,sym;
int ch;
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* check the next character */
if ((ch = xlgetc(fptr)) == '@')
sym = s_comat;
else {
xlungetc(fptr,ch);
sym = s_comma;
}
/* make the return value */
return (consa(pquote(fptr,sym)));
}
/* rmlpar - read macro for '(' */
LVAL rmlpar()
{
LVAL fptr,mch;
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* make the return value */
return (consa(plist(fptr)));
}
/* rmrpar - read macro for ')' */
LVAL rmrpar()
{
xlfail("misplaced right paren");
}
/* rmsemi - read macro for ';' */
LVAL rmsemi()
{
LVAL fptr,mch;
int ch;
/* get the file and macro character */
fptr = xlgetfile();
mch = xlgachar();
xllastarg();
/* skip to end of line */
while ((ch = xlgetc(fptr)) != EOF && ch != '\n')
;
/* return nil (nothing read) */
return (NIL);
}
/* pcomment - parse a comment delimited by #| and |# */
LOCAL pcomment(fptr)
LVAL fptr;
{
int lastch,ch,n;
/* look for the matching delimiter (and handle nesting) */
for (n = 1, lastch = -1; n > 0 && (ch = xlgetc(fptr))